package com.example.sicnuaccountingapp.ui.budget

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.sicnuaccountingapp.base.BaseViewModel
import com.example.sicnuaccountingapp.base.UiState
import com.example.sicnuaccountingapp.data.entity.Budget
import com.example.sicnuaccountingapp.data.entity.Category
import com.example.sicnuaccountingapp.data.entity.TransactionType
import com.example.sicnuaccountingapp.data.repository.BudgetRepository
import com.example.sicnuaccountingapp.data.repository.CategoryRepository
import com.example.sicnuaccountingapp.data.repository.TransactionRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import java.time.LocalDate
import java.time.ZoneId
import javax.inject.Inject

@HiltViewModel
class BudgetViewModel @Inject constructor(
    private val budgetRepository: BudgetRepository,
    private val categoryRepository: CategoryRepository,
    private val transactionRepository: TransactionRepository
) : ViewModel() {

    private val _state = MutableStateFlow<BudgetUiState>(BudgetUiState.Loading)
    val state: StateFlow<BudgetUiState> = _state.asStateFlow()

    private var currentUserId: Long = -1L
    private val _categories = MutableStateFlow<List<Category>>(emptyList())
    val categories: StateFlow<List<Category>> = _categories.asStateFlow()

    fun setUserId(userId: Long) {
        currentUserId = userId
        loadBudgets()
        loadCategories()
    }

    private fun loadBudgets() {
        viewModelScope.launch {
            try {
                _state.value = BudgetUiState.Loading

                // 获取当月开始和结束时间
                val now = LocalDate.now()
                val startOfMonth = now.withDayOfMonth(1)
                    .atStartOfDay(ZoneId.systemDefault())
                    .toInstant()
                    .toEpochMilli()
                val endOfMonth = now.withDayOfMonth(now.lengthOfMonth())
                    .atTime(23, 59, 59)
                    .atZone(ZoneId.systemDefault())
                    .toInstant()
                    .toEpochMilli()

                // 合并预算和支出数据
                combine(
                    budgetRepository.getActiveBudgets(currentUserId),
                    transactionRepository.getTransactionsByDateRange(
                        currentUserId,
                        startOfMonth,
                        endOfMonth
                    ),
                    categoryRepository.getAllCategories(currentUserId)
                ) { budgets, transactions, categories ->
                    // 计算总支出
                    val totalExpense = transactions
                        .filter { it.type == TransactionType.EXPENSE }
                        .sumOf { it.amount }

                    // 计算总预算
                    val totalBudget = budgets.sumOf { it.amount }

                    // 计算月度预算信息
                    val monthlyBudgetInfo = MonthlyBudgetInfo(
                        totalBudget = totalBudget,
                        totalExpense = totalExpense,
                        progress = if (totalBudget > 0) {
                            (totalExpense / totalBudget * 100).toFloat()
                        } else 0f
                    )

                    // 计算分类预算信息
                    val categoryBudgets = budgets.mapNotNull { budget ->
                        val category = categories.find { it.categoryId == budget.categoryId }
                        category?.let {
                            val categoryExpense = transactions
                                .filter { 
                                    it.type == TransactionType.EXPENSE && 
                                    it.categoryId == budget.categoryId 
                                }
                                .sumOf { it.amount }
                            
                            CategoryBudgetInfo(
                                budget = budget,
                                category = category,
                                expense = categoryExpense,
                                progress = if (budget.amount > 0) {
                                    (categoryExpense / budget.amount * 100).toFloat()
                                } else 0f
                            )
                        }
                    }

                    BudgetUiState.Success(
                        monthlyBudget = monthlyBudgetInfo,
                        categoryBudgets = categoryBudgets
                    )
                }.collect { state ->
                    _state.value = state
                }
            } catch (e: Exception) {
                _state.value = BudgetUiState.Error(e.message ?: "加载失败")
            }
        }
    }

    private fun loadCategories() {
        viewModelScope.launch {
            categoryRepository.getAllCategories(currentUserId)
                .collect { categories ->
                    _categories.value = categories
                }
        }
    }

    fun addBudget(categoryId: Long?, amount: Double) {
        viewModelScope.launch {
            try {
                val budget = Budget(
                    userId = currentUserId,
                    categoryId = categoryId,
                    amount = amount,
                    startDate = LocalDate.now().withDayOfMonth(1)
                        .atStartOfDay(ZoneId.systemDefault())
                        .toInstant()
                        .toEpochMilli(),
                    endDate = LocalDate.now().withDayOfMonth(LocalDate.now().lengthOfMonth())
                        .atTime(23, 59, 59)
                        .atZone(ZoneId.systemDefault())
                        .toInstant()
                        .toEpochMilli()
                )
                budgetRepository.addBudget(budget)
                loadBudgets()
            } catch (e: Exception) {
                _state.value = BudgetUiState.Error(e.message ?: "添加预算失败")
            }
        }
    }

    fun updateBudget(budget: Budget) {
        viewModelScope.launch {
            try {
                budgetRepository.updateBudget(budget)
                loadBudgets()
            } catch (e: Exception) {
                _state.value = BudgetUiState.Error(e.message ?: "更新预算失败")
            }
        }
    }

    fun deleteBudget(budget: Budget) {
        viewModelScope.launch {
            try {
                budgetRepository.deleteBudget(budget)
                loadBudgets()
            } catch (e: Exception) {
                _state.value = BudgetUiState.Error(e.message ?: "删除预算失败")
            }
        }
    }
} 